import { httpUtilConfig } from "dcloud-core"
import { stringify } from 'qs';

// 要关闭加密把这个参数改为false
const paramsEnc = true;

let filterEncryption = true

class HttpUtil{
    constructor( requestConfig, hud = true, timeOut, isBackAll = false, contentType) {
        let { url, parmas, method, headers, body} = requestConfig;
        this.utilConfig = new httpUtilConfig();
        method = method? method : 'GET';
        console.log('请求url',url )
        console.log('加密前参数',parmas )

        if(!url.includes('/appointment') || url.includes('ticket/verify')){
            filterEncryption = false;
        }else{
            filterEncryption = true;
        }

        // 加密版
        if(paramsEnc && filterEncryption){
            parmas = this.utilConfig.encryption(parmas, method);
        }

        this.opt = {
            headers :  {...this.utilConfig.getHeaders(contentType, parmas),...headers},
            method : method,
            mode: 'cors'
        }


        if (requestConfig.formData) {
            delete this.opt.headers["Content-Type"];
            body = requestConfig.formData;
        }

        //如果传了body
        if(body){
            this.opt.body = body
        }else{
            if (method === 'POST') {
                if (this.opt.headers["Content-Type"] === 'application/x-www-form-urlencoded') {
                    this.opt.body = this.dataToString(parmas);
                } else {
                    this.opt.body = JSON.stringify(parmas);
                }
            }
        }

        this.parmas = parmas? parmas : {};
        this.response = this.utilConfig.getResponse();
        this.url = url;
        this.hud = hud;
        this.isBackAll = isBackAll;
        this.timeOut = timeOut ? timeOut : this.utilConfig.getTimeOut();
        if(this.opt.method == 'GET')
            this.url = this.getUrl();
        this.httpFetch = this.httpFetch.bind(this);
    }

    /**
     * 获取数据包信息
     * @param res
     * @returns {{flag: boolean, httpCode: null, message: null, error: null, data: {}}|*}
     */
    packResponse(res) {
        this.response.data =  res.data;
        return this.response;
    }


        /**
     * 服务器错误响应
     * @param error
     * @returns {{flag: boolean, httpCode: null, message: null, error: null, data: {}}|*}
     */
    packError(error,code) {
        this.response.error = error;
        this.response.httpCode = code;
        return this.response;
    }


/*    /!**
     * 服务器错误响应
     * @param error
     * @returns {{flag: boolean, httpCode: null, message: null, error: null, data: {}}|*}
     *!/
    packError(error,code) {
        this.response.error = error;
        this.response.httpCode = code || error.code;
        this.response.message = this.response.message || error.message || error;
        return this.response;
    }*/

    /**
     * 网络请求
     * @returns {Promise|Promise<T>}
     */
    httpFetch(){
        let _this = this;
        let abort_promise = new Promise((resolve, reject) => {
            setTimeout(()=>{
                reject({
                    message:'网络请求超时',
                    status:60000
                })
            }, this.timeOut)
        });

        console.log('opt:',this.opt,' | url:', this.url);
        let abortable_promise = Promise.race([
            fetch(this.url, this.opt),
            abort_promise
        ]);

        // if(this.hud==true) global.ActivityIndicator.open(); // loding框
        return new Promise((resolve, reject) => {
            console.log('request:', 'httpUrl:', this.url, '\n', 'httpData:', this.opt);
            abortable_promise.then((response)=>{
                this.status = response.status;
                this.utilConfig.detect(response,this).then((res) => {
                    // 请求成功,是否返回全部数据
                    if (this.isBackAll == true){
                        return response;
                    }else
                        return res;
                }).catch((error, msg) => {
                    // 服务器响应异常
                    // global.ActivityIndicator.close(); // loding框
                    console.log('系统异常:', this.url, msg || response.status);
                    resolve(this.packError(msg || '未知错误', response.status));
                    return false;
                });
                return response.json();
            }).then((json)=> {
                // global.ActivityIndicator.close(); // loding框

                console.log('访问结果:', this.url, json);
                if(json) {
                    // 参数解密
                    if(paramsEnc && filterEncryption){
                        json = this.utilConfig.decrypt(json, this.opt.method);
                    }
                    console.log('解密后的返回值', json)
                    this.utilConfig.detectBusiness(json).then((res) => {
                        // 请求成功
                        resolve(res);
                    }).catch((error, msg) => {
                        // 服务器响应异常
                      // reject(this.packError(error, json.code));
                       resolve(this.packError(msg || '未知错误', json.status));
                        return false;
                    });
                }

              //  resolve(res);
            }).catch((error) => {
                // global.ActivityIndicator.close(); // loding框
                console.log('访问出错:', this.url, this.status || '' , error.message);
                // throw new Error(error);
            });
        })
    }


    /**
     * get方法url加工
     * @returns {*}
     */
    getUrl() {
        if(this.opt.method === "GET" && this.parmas){
            const para = this.dataToString(this.parmas) ? '?'+this.dataToString(this.parmas) : this.dataToString(this.parmas)
            return `${this.url}${para}`
        }
        return this.url
    }

    dataToString(params){
        return stringify(params)
    }
}

/**
 * import { httpUtil } from 'dcloud-utils'; httpUtil.get(...)
 * @param url       请求地址
 * @param parmas    参数
 * @param headers   请求头
 * @param hud       是否需要loading
 * @param timeOut   请求超时时间
 * @param isBackAll 是否返回整个response
 * @returns {Promise|Promise<T>}
 */
const get = ( url, parmas, config = {} ) =>{
    const {headers, hud=true, timeOut, isBackAll=false} = config
    console.log(config)
    return new Promise((resolve, reject) => {
        let requestConfig = {
            url, parmas, method:'GET', headers
        }
        const util = new HttpUtil(requestConfig, hud, timeOut, isBackAll);
        util.httpFetch().then((res)=>{
            resolve(res);
        }).catch((error) => {
            reject(error);
        });
    });
}

/**
 * import { httpUtil } from 'dcloud-utils'; httpUtil.post(...)
 * @param url       请求地址
 * @param parmas    参数
 * @param headers   请求头
 * @param hud       是否需要loading
 * @param timeOut   请求超时时间
 * @param isBackAll 是否返回整个response
 * @returns {Promise|Promise<T>}
 */

const post = ( url, parmas, contentType, config={} )=>{
    const {headers, body, hud=true, timeOut, isBackAll=false} = config
    console.log(config)
    return new Promise((resolve, reject) => {
        let requestConfig = {
            url, parmas, method:'POST', headers,body
        }
        const util = new HttpUtil(requestConfig, hud, timeOut, isBackAll, contentType);
        util.httpFetch().then((res)=>{
            resolve(res)
        }).catch((error) => {
            reject(error)
        });
    });
}

/**
 * 表单提交
 * @param url
 * @param parmas
 * @param type
 * @param config
 * @returns {Promise<any> | Promise<*>}
 */
const formData = (url, parmas, type, config={}) => {
    const {headers, body, hud=true, timeOut, isBackAll=false} = config;
    return new Promise((resolve, reject) => {
        let formData = new FormData();
        for(let key in parmas) {
            formData.append(key, parmas[key])
        }
        let requestConfig = {
            url, formData, method:type || 'POST', headers,body
        }
        const util = new HttpUtil(requestConfig, hud, timeOut, isBackAll);
        util.httpFetch().then((res)=>{
            resolve(res);
        }).catch((error) => {
            console.error(error.message);
            reject(error);
        });
    });
}

// httpUtil.post(httpUrlConfig.uploadImages, {}, headers, formData)
const postUpload = ( url, parmas,headers,body,config={} )=>{
    const {  hud=true, timeOUt, isBackAll=false} = config
    return new Promise((resolve, reject) => {
        let requestConfig = {
            url, parmas, method:'POST', headers,body
        }
        const util = new HttpUtil(requestConfig, hud, timeOut, isBackAll);
        util.httpFetch().then((res)=>{
            resolve(res)
        }).catch((error) => {
            reject(error)
        });
    });
}

export default {
    get,
    post,
    formData,
    postUpload
}
